package top.zhangjianyong.tools.indicator.strategy.impl;

import org.springframework.stereotype.Component;
import top.zhangjianyong.tools.entity.ETFData;
import top.zhangjianyong.tools.indicator.context.IndicatorContext;
import top.zhangjianyong.tools.indicator.model.TechnicalIndicatorResult;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

/**
 * 价格位置比率指标计算器
 * 计算收盘价相对于最高/最低价的位置（日内位置）
 *
 * @author zhangjianyong
 * @date 2024/01/01
 */
@Component
public class PricePositionIndicator extends AbstractIndicator {

    private static final String INDICATOR_NAME = "PRICE_POSITION";

    @Override
    public String getName() {
        return INDICATOR_NAME;
    }

    @Override
    public int getMinDataSize() {
        return 1; // 至少需要1个数据点
    }

    @Override
    protected TechnicalIndicatorResult doCalculate(IndicatorContext context) {
        List<ETFData> dataList = context.getDataList();

        if (dataList.isEmpty()) {
            return TechnicalIndicatorResult.failure(getName(), "数据列表为空");
        }

        // 获取当前数据点
        ETFData currentData = dataList.get(dataList.size() - 1);
        BigDecimal currentPrice = currentData.getValue();

        // 计算最近N个交易日内的最高价和最低价（使用收盘价近似）
        // 由于只有收盘价，我们使用最近一段时间的最高和最低收盘价
        int lookbackPeriod = Math.min(20, dataList.size());
        List<ETFData> subList = dataList.subList(dataList.size() - lookbackPeriod, dataList.size());

        BigDecimal highest = subList.stream()
            .map(ETFData::getValue)
            .max(BigDecimal::compareTo)
            .orElse(currentPrice);

        BigDecimal lowest = subList.stream()
            .map(ETFData::getValue)
            .min(BigDecimal::compareTo)
            .orElse(currentPrice);

        // 计算价格位置比率
        // 位置比率 = (当前价格 - 最低价) / (最高价 - 最低价) * 100
        BigDecimal positionRatio = BigDecimal.ZERO;
        BigDecimal range = highest.subtract(lowest);

        if (range.compareTo(BigDecimal.ZERO) != 0) {
            positionRatio = currentPrice.subtract(lowest)
                .divide(range, 4, RoundingMode.HALF_UP)
                .multiply(new BigDecimal(100));
        } else {
            positionRatio = new BigDecimal(50); // 如果最高价等于最低价，返回中间位置
        }

        // 限制在0-100范围内
        if (positionRatio.compareTo(BigDecimal.ZERO) < 0) {
            positionRatio = BigDecimal.ZERO;
        } else if (positionRatio.compareTo(new BigDecimal(100)) > 0) {
            positionRatio = new BigDecimal(100);
        }

        TechnicalIndicatorResult result = TechnicalIndicatorResult.success(getName());
        result.addValue("price_position_ratio", positionRatio.setScale(2, RoundingMode.HALF_UP));
        result.addValue("price_position_highest", highest);
        result.addValue("price_position_lowest", lowest);

        return result;
    }
}

